# 4. viseme_controller.py
import time
import numpy as np
import sdl2
from text_render import pil_image_to_texture

# ============  528修改嘴型帧切换控制器，新的切换逻辑 ，611 主要还是静默嘴型，过渡动画的切换问题======================
class VisemeController:
    def __init__(self, viseme_players, transition_players, reverse_players, transition_reverse_players, default_player, static_mouth_cache, word_timeline, viseme_timeline):
        self.viseme_players = viseme_players          # M1-M7 正播
        self.transition_players = transition_players  # M1_M2, M2_M3...
        self.reverse_players = reverse_players        # M1-M7 倒播（闭嘴用）
        self.transition_reverse_players = transition_reverse_players # M2_M1,M4_M3... 过渡动画倒播
        self.default_player = default_player
        self.static_mouth_cache = static_mouth_cache # ✅ 保存下来备用
        self.word_timeline = word_timeline
        self.viseme_timeline = viseme_timeline
        self.current_viseme = None
        self.last_segment = (None, None)
        self.current_player = default_player
        self.last_word = None
        self.last_viseme = None
        self.last_ts = time.time()
        self.frame_count = 0
        self.word_viseme_info = None
        self.last_play_direction = "forward"  # 控制重复 viseme （M1 M1 M1）轮流正播 / 倒播

    def update(self, viseme_timeline, delta_ms):
        found = False
        for i, (begin, end, viseme) in enumerate(viseme_timeline):
            if begin <= delta_ms <= end:
                if viseme != self.current_viseme or self.last_segment != (begin, end):
                    from_viseme = self.last_viseme
                    to_viseme = viseme
                    use_reverse = False
                    player = None
                    
                    # ✅ 条件1：与上次 viseme 相同，但时间段不同 → 连续重复
                    is_same_viseme = (from_viseme == to_viseme)
                    is_new_segment = (self.last_segment != (begin, end))
                    
                    if is_same_viseme and is_new_segment:
                        if self.last_play_direction == "forward":
                            player = self.reverse_players.get(to_viseme)
                            use_reverse = True
                            self.last_play_direction = "reverse"
                            print(f"[🔁倒播] 连续 viseme={to_viseme}，执行倒播")
                        else:
                            player = self.viseme_players.get(to_viseme)
                            self.last_play_direction = "forward"
                            print(f"[🔁正播] 连续 viseme={to_viseme}，执行正播")
                            
                    # ✅ 条件2：不同 viseme → 查找过渡动画
                    elif from_viseme and from_viseme != to_viseme:
                        key = f"{from_viseme}_{to_viseme}"
                        reverse_key = f"{to_viseme}_{from_viseme}"
                        if key in self.transition_players:
                            player = self.transition_players[key]
                            self.last_play_direction = "forward"
                            print(f"[➡️过渡] viseme={key} 正播")
                        elif reverse_key in self.transition_reverse_players:
                            player = self.transition_reverse_players[reverse_key]
                            use_reverse = True
                            self.last_play_direction = "reverse"
                            print(f"[⬅️过渡] viseme={reverse_key} 倒播")

                    # ✅ 条件3：首次 or 没找到过渡 → 使用目标 viseme 正播
                    if not player:
                        player = self.viseme_players.get(to_viseme, self.default_player)
                        self.last_play_direction = "forward"
                        print(f"[✅默认] viseme={to_viseme} 正播")
                          
                    # 🎯 设置帧序列
                    frames = choose_frames(end - begin, 0, 24)
                    if use_reverse:
                        frames = frames[::-1]
                    # print(f"[切换] 当前 viseme={viseme}，使用播放器: {player} 播放帧列表：{frames}")
                    player.set_play_sequence(frames)
                    
                    # 更新控制状态 保存渲染的嘴型frame
                    self.current_viseme = to_viseme
                    self.current_player = player
                    self.frame_count = 0
                    self.last_segment = (begin, end)
                    self.last_viseme = to_viseme
                    if i < len(self.word_timeline):
                        word_text = self.word_timeline[i][2]  # 只取第3个字段
                    else:
                        word_text = "?"
                    self.word_viseme_info = (word_text, begin, end, to_viseme) # word_timeline[i][2]可能多添加了一个参数
                
                found = True
                break

            if i > 0:
                prev_begin, prev_end, prev_viseme = viseme_timeline[i - 1]
                gap = begin - prev_end
                if prev_end < delta_ms < begin and gap <= 150:
                    if prev_viseme != self.current_viseme or self.last_segment != (prev_begin, prev_end):
                        print(f"[延长播放] delta={delta_ms:.0f}ms 处于 {prev_viseme} 段后空隙，延长播放")
                        self.current_viseme = prev_viseme
                        self.current_player = self.viseme_players.get(prev_viseme, self.default_player)
                        frames = choose_frames(prev_end - prev_begin, 0, 24)
                        if self.current_player.reverse:
                            frames = frames[::-1] # 倒播代码
                        self.current_player.set_play_sequence(frames)
                        self.frame_count = 0
                        self.last_segment = (prev_begin, prev_end)
                        self.last_viseme = prev_viseme
                        self.word_viseme_info = (self.word_timeline[i - 1][2], prev_begin, prev_end, prev_viseme) # 同样也是可能多一个参数
                    found = True
                    break

        if not found:
            #print(f"[DEBUG] 当前 delta={delta_ms:.0f}ms 未命中任何 viseme，维持当前嘴型")
            pass

    def render_current_frame(self, renderer):
        if self.current_viseme is None:
            self.static_mouth_cache.render(renderer)
            return
        image = self.current_player.render_next_frame()
        self.frame_count += 1
        texture = pil_image_to_texture(image, renderer)
        sdl2.SDL_RenderCopy(renderer, texture, None, None)
        sdl2.SDL_DestroyTexture(texture)

        is_last_viseme = self.last_segment == self.viseme_timeline[-1][:2]

        # ✅ 日志记录
        with open("mouth_frame_log_613.txt", "a") as f:
            current_time = time.time()
            diff = current_time - self.last_ts
            f.write(f"{current_time:.3f}s | diff: {diff:.3f}s | viseme={self.current_viseme} | frame={self.current_player.current_frame}\n")
            self.last_ts = current_time
        
        # 6/10 修改，替换成固定的op
        if self.current_player.current_frame >= 23:
            if is_last_viseme:
                self.current_viseme = None
                self.current_player = self.static_mouth_cache
                print(f"[INFO] 最后嘴型 {self.last_viseme} 播放完成，切换为静态闭嘴")

# 528修改-lin，根据百分比选择渲染帧的范围，528修改，新增形参 ,修改好👌
# 612 修改，根据刷新率，假定为60hz，每帧刷新时间1000/60=17ms,时间间隔200ms,可以刷新 int(200/17) frame
def choose_frames(phoneme_duration_ms, ip, op):
    #screen_refresh_rate = 60
    #frame_time_ms = 1000 / screen_refresh_rate  # ≈16.67ms
    total_playable = int(phoneme_duration_ms / 20) #假设屏幕刷新率有延迟25ms，22ms就好一些

    if total_playable <= 2:
        return [ip, op - 1]

    num_middle = total_playable - 2
    raw_middle = np.linspace(ip + 1, op - 2, num=num_middle, endpoint=True) #list 均匀分布取值
    middle_frames = sorted(set(int(round(f)) for f in raw_middle if ip + 1 <= f <= op - 2))

    return [ip] + middle_frames + [op - 1]
